package com.demo.cms.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.demo.cms.dao.NaviDao;
import com.demo.cms.dao.RoleNaviDao;
import com.demo.cms.model.Navi;
import com.demo.cms.model.RoleNavi;
import com.demo.cms.service.NaviService;
import com.demo.core.dao.base.support.ResultSearchResult;
import com.demo.core.dao.base.support.SearchArgumentSupport;
import com.demo.core.model.support.AdjacencyListModel;

/**
 * 导航服务实现类
 * 
 * @author ryuu.kk
 *
 */
public class NaviServiceImpl implements NaviService {

	/**
	 * 导航数据访问层
	 */
	private NaviDao naviDao;
	
	/**
	 * 角色导航管理数据访问层
	 */
	private RoleNaviDao roleNaviDao;
	
	@Override
	public Long save(Navi navi) {
		return save(navi, null);
	}
	
	@Override
	@Transactional
	public Long save(Navi navi, List<RoleNavi> roleNaviList) {
		Long id = naviDao.insert(navi);
		if (roleNaviList != null) {
			for (RoleNavi rn : roleNaviList) {
				rn.setNaviId(id);
				roleNaviDao.insert(rn);
			}
		}
		return id;
	}

	@Override
	public boolean exists(Long id) {
		return naviDao.exists(id);
	}

	@Override
	public void update(Long id, Navi navi) {
		// 更新条件
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("id", id);
		params.put("navi", navi);
		// 更新
		naviDao.update(navi, params);
	}

	@Override
	public void update(Long id, boolean enabled, String status) {
		// 更新条件
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("id", id);
		// 更新
		naviDao.enabled(enabled, status, params);
	}
	
	@Override
	public void delete(Long id) {
		// 包含级联删除的RoleNavi
		naviDao.delete(id);
	}
	
	@Override
	public void deleteRoleNavi(Long siteId, Long roleNaviId) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("id", roleNaviId);
		params.put("siteId", siteId);
		roleNaviDao.delete(params);
	}
	
	@Override
	public void deleteRoleNavi(Long siteId, Long naviId, Long roleId) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("naviId", naviId);
		params.put("siteId", siteId);
		params.put("roleId", roleId);
		roleNaviDao.delete(params);
	}

	@Override
	public void deleteAll(Long siteId) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("siteId", siteId);
		naviDao.delete(params);
	}
	
	@Override
	public Navi find(Long id) {
		return naviDao.select(id);
	}

	@Override
	public List<Navi> findList(Long siteId, Long channelId, Long categoryId, Long articleId) {
		return findList(siteId, null, channelId, categoryId, articleId);
	}
	
	@Override
	public List<Navi> findList(Long siteId) {
		return findList(siteId, null, null, null, null);
	}

	@Override
	public List<Navi> findList(Long siteId, Long pid) {
		return findList(siteId, pid, null, null, null);
	}

	@Override
	public Navi query(Long siteId, Long id) {
		List<Navi> naviList = query(siteId, id, null, null, null, null, 1);
		return naviList.size() == 1 ? naviList.get(0) : null;
	}
	
	@Override
	public List<Navi> query(Long siteId, Long roleId, int... level) {
		return query(siteId, null, roleId, null, null, null, level);
	}

	@Override
	public List<Navi> query(Long siteId, Long channelId, Long categoryId, Long articleId, int... level) {
		return query(siteId, null, null, channelId, categoryId, articleId, level);
	}

	@Override
	public AdjacencyListModel queryTree(Long siteId, int... level) {
		return queryTree(siteId, null, null, null, level);
	}

	@Override
	public AdjacencyListModel queryTree(Long siteId, Long id, Boolean enabled, int... level) {
		return queryTree(siteId, id, null, enabled, level);
	}

	@Override
	public AdjacencyListModel queryTree(Long siteId, Long id, Long roleId, Boolean enabled, int... level) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("siteId", siteId);
		params.put("id", id);
		params.put("enabled", enabled);
		params.put("roleId", roleId);
		if (level != null && level.length > 0) {
			List<?> depthList = CollectionUtils.arrayToList(level);
			params.put("depthList", depthList);
		}
		return naviDao.tree(params);
	}
	
	@Override
	public ResultSearchResult<Navi> search(Long siteId, int firstResult, int maxResults) {
		SearchArgumentSupport args = new SearchArgumentSupport(firstResult, maxResults);
		return search(siteId, args);
	}
	
	@Override
	public ResultSearchResult<Navi> search(Long siteId, SearchArgumentSupport args) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("siteId", siteId);
		return naviDao.search(params, args);
	}
	
	@Override
	public ResultSearchResult<Navi> search(Long siteId, Long pid,
			SearchArgumentSupport args) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("siteId", siteId);
		params.put("pid", pid);
		return naviDao.search(params, args);
	}
	
	private List<Navi> findList(Long siteId, Long pid, Long channelId, Long categoryId, Long articleId) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("siteId", siteId);
		params.put("pid", pid);
		params.put("channelId", channelId);
		params.put("categoryId", categoryId);
		params.put("articleId", articleId);
		return naviDao.select(params);
	}

	private List<Navi> query(Long siteId, Long id, Long roleId, Long channelId, Long categoryId, Long articleId, int... level) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("siteId", siteId);
		params.put("id", id);
		if (level != null && level.length > 0) {
			List<?> depthList = CollectionUtils.arrayToList(level);
			params.put("depthList", depthList);
		}
		params.put("roleId", roleId);
		params.put("channelId", channelId);
		params.put("categoryId", categoryId);
		params.put("articleId", articleId);
		return naviDao.query(params);
	}
	
	public void setRoleNaviDao(RoleNaviDao roleNaviDao) {
		this.roleNaviDao = roleNaviDao;
	}

	public void setNaviDao(NaviDao naviDao) {
		this.naviDao = naviDao;
	}

	@Override
	public Navi getDefaultModel(Long siteId) {
		Navi navi = new Navi();
		
		navi.setName("ROOT");
		navi.setTitle("ROOT");
		navi.setAnonymous(Boolean.TRUE);
		navi.setEnabled(Boolean.TRUE);
		navi.setPid(null);
		navi.setSiteId(siteId);
		navi.setStatus("RWD");
		navi.setType(Navi.TYPE_MENU);
		navi.setPriority(0);
		return navi;
	}
}
